import {
  AppstoreAddOutlined,
  AppstoreFilled,
  DeleteOutlined,
  PlusOutlined,
  SettingOutlined,
} from '@ant-design/icons';
import { Button } from 'antd';
import React, { useCallback, useState } from 'react';
import { NodeProps } from 'reactflow';
import { useContextSelector } from 'use-context-selector';

import FormLabel from '@/components/MyBox/FormLabel';
import MyTooltip from '@/components/tooltip';
import QuestionTip from '@/components/tooltip/QuestionTip';
import { useConfirm } from '@/hooks/use-confirm';
import { t } from '@/locales/i18n';
import {
  FlowNodeTypeEnum,
  VARIABLE_NODE_ID,
  WorkflowIOValueTypeEnum,
} from '@/types/workflow/constant';
import { FlowNodeInputItemType, ReferenceValueProps } from '@/types/workflow/io';
import { FlowNodeItemType } from '@/types/workflow/node';
import { isWorkflowStartOutput } from '@/types/workflow/template/system/workflowStart';

import { WorkflowContext } from '../../../context';
import Container from '../../flow/Container';
import IOTitle from '../../flow/IOTitle';
import NodeCard from '../render/NodeCard';
import { ReferSelector, useReference } from '../render/RenderInput/templates/Reference';
import ValueTypeLabel from '../render/ValueTypeLabel';

import PluginOutputEditModal, { defaultOutput } from './PluginOutputEditModal';

const customOutputConfig = {
  selectValueTypeList: Object.values(WorkflowIOValueTypeEnum),

  showDefaultValue: true,
};

const NodePluginOutput = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
  const { nodeId, inputs } = data;
  const onChangeNode = useContextSelector(WorkflowContext, (v) => v.onChangeNode);

  const [editField, setEditField] = useState<FlowNodeInputItemType>();

  return (
    <NodeCard
      minW="300px"
      selected={selected}
      menuForbid={{
        debug: true,
        copy: true,
        delete: true,
      }}
      {...data}
    >
      <Container className="mt-1" mt={1}>
        <div className="nodrag relative flex cursor-default items-center">
          <IOTitle className="mb-0" text={t('core.workflow.Custom outputs')} />
          <div className="flex-1" />
          <Button type="text" icon={<PlusOutlined />} onClick={() => setEditField(defaultOutput)}>
            {t('common.Add New')}
          </Button>
        </div>

        {/* render input */}
        <div className="mt-2">
          {inputs.map((input, index) => (
            <div className={`${index === inputs.length - 1 ? '' : 'mb-3'}`} key={input.key}>
              <Reference nodeId={nodeId} keys={inputs.map((input) => input.key)} input={input} />
            </div>
          ))}
        </div>
      </Container>
      {!!editField && (
        <PluginOutputEditModal
          customOutputConfig={customOutputConfig}
          defaultOutput={editField}
          keys={inputs.map((input) => input.key)}
          onClose={() => setEditField(undefined)}
          onSubmit={({ data }) => {
            onChangeNode({
              nodeId,
              type: 'addInput',
              value: data,
            });
          }}
        />
      )}
    </NodeCard>
  );
};

export default React.memo(NodePluginOutput);

function Reference({
  nodeId,
  keys,
  input,
}: {
  nodeId: string;
  keys: string[];
  input: FlowNodeInputItemType;
}) {
  const { ConfirmModal, openConfirm } = useConfirm({
    type: 'delete',
    content: t('confirm_delete_field_tip'),
  });
  const onChangeNode = useContextSelector(WorkflowContext, (v) => v.onChangeNode);
  const nodeList = useContextSelector(WorkflowContext, (v) => v.nodeList);

  const [editField, setEditField] = useState<FlowNodeInputItemType>();

  const onSelect = useCallback(
    (e: ReferenceValueProps) => {
      const workflowStartNode = nodeList.find(
        (node) => node.flowNodeType === FlowNodeTypeEnum.workflowStart,
      );

      const value =
        e[0] === workflowStartNode?.id && !isWorkflowStartOutput(e[1])
          ? [VARIABLE_NODE_ID, e[1]]
          : e;

      onChangeNode({
        nodeId,
        type: 'updateInput',
        key: input.key,
        value: {
          ...input,
          value,
        },
      });
    },
    [input, nodeId, nodeList, onChangeNode],
  );

  const { referenceList, formatValue } = useReference({
    nodeId,
    valueType: input.valueType,
    value: input.value,
  });

  const onUpdateField = useCallback(
    ({ data }: { data: FlowNodeInputItemType }) => {
      if (!data.key) return;

      onChangeNode({
        nodeId,
        type: 'replaceInput',
        key: input.key,
        value: data,
      });
    },
    [input.key, nodeId, onChangeNode],
  );
  const onDel = useCallback(() => {
    onChangeNode({
      nodeId,
      type: 'delInput',
      key: input.key,
    });
  }, [input.key, nodeId, onChangeNode]);

  return (
    <>
      <div className="mb-1 flex items-center justify-between">
        <div className="flex">
          <FormLabel required={input.required}>{input.label}</FormLabel>
          {input.description && <QuestionTip className="ml-1" title={input.description} />}
          {/* value */}
          <ValueTypeLabel valueType={input.valueType} valueDesc={input.valueDesc} />

          <Button
            icon={<SettingOutlined />}
            className="ml-3 text-gray-600 hover:text-gray-700"
            onClick={() => setEditField(input)}
          />

          <Button
            icon={<DeleteOutlined />}
            className="ml-3 text-gray-600 hover:text-error"
            onClick={() => openConfirm(onDel)}
          />
        </div>
        <MyTooltip title={t('plugin_output_tool')}>
          <Button
            icon={input.isToolOutput !== false ? <AppstoreFilled /> : <AppstoreAddOutlined />}
            className="mr-2 text-gray-600 hover:text-error"
            onClick={() => setEditField(input)}
          />
        </MyTooltip>
      </div>
      <ReferSelector
        placeholder={t((input.referencePlaceholder as any) || 'select_reference_variable')}
        list={referenceList}
        value={formatValue}
        onSelect={onSelect}
      />

      {!!editField && (
        <PluginOutputEditModal
          defaultOutput={editField}
          customOutputConfig={customOutputConfig}
          keys={keys}
          onClose={() => setEditField(undefined)}
          onSubmit={onUpdateField}
        />
      )}
      <ConfirmModal />
    </>
  );
}
